/*
 * Ingenic JZ MMC driver
 * wqshao  <wangquan.shao@ingenic.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include <common.h>
#include <malloc.h>
#include <sdhci.h>
#include <asm/arch/jzsoc.h>
#include "jz_sdhci_regs.h"

#ifdef CONFIG_SPL_BUILD
/* SPL will only use a single MMC device (CONFIG_JZ_MMC_SPLMSC) */
struct sdhci_host jz_sdhci_host[1];
#endif

static char *JZ_NAME = "MSC";

static int jz_sdhci_init(u32 regbase, int index, int clock_div)
{
	struct sdhci_host *host = NULL;
	uint32_t real_rate = CONFIG_SYS_MPLL_FREQ / clock_div;

#ifdef CONFIG_SPL_BUILD
	host = &jz_sdhci_host;
#else
	host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
#endif
	if (!host) {
		printf("sdhci__host malloc fail!\n");
		return 1;
	}

	host->name = JZ_NAME;
	host->ioaddr = (void *)regbase;
	host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE
		| SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;

	host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
	host->version = sdhci_readw(host, SDHCI_HOST_VERSION);

	host->set_control_reg = NULL;
	host->set_clock = NULL;
	host->index = index;

	host->host_caps = MMC_MODE_HC; //for emmc OCR

	return add_sdhci(host, real_rate, 300000);
}

void jz_mmc_init(int clock_div)
{
	unsigned int val;
#if defined(CONFIG_JZ_MMC_MSC0) && (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_JZ_MMC_SPLMSC))
	jz_sdhci_init(MSC0_BASE, 0, clock_div);
#endif
#if defined(CONFIG_JZ_MMC_MSC1) && (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_JZ_MMC_SPLMSC))
	jz_sdhci_init(MSC1_BASE, 1, clock_div);
#endif
#if defined(CONFIG_JZ_MMC_MSC2) && (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_JZ_MMC_SPLMSC))
	jz_sdhci_init(MSC2_BASE, 2, clock_div);
	val = readl(CPM_MSC2_CLK_R);
	val &= ~(0x3 << 15);
	val |= 0x3 << 15;
	writel(val, CPM_MSC2_CLK_R);
#endif
}

